package com.study.zk.config;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.RetryOneTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;

/**
 * @author: chenhs
 * @date: Created in 6:27 2019/12/9
 **/
@Component
public class SystemConfigUtil {

    Properties remoteProperties = new Properties();

    public String getProperty(String key) {
        return remoteProperties.getProperty(key);
    }


    @Value("${config.zookeeper.url}")
    String zkUrl;

    @Value("${config.zookeeper.nodename}")
    String nodename;


    /**
     * todo 启动系统的时候读取远程配置中心的系统配置信息表
     * <p>
     * 对象初始化之后触发执行
     */
    @PostConstruct
    public void init() {
        //todo 1.读取数据表
        //todo 2.保存到java内存（对象）
        //todo 3.配置更新的时候，如何知晓？（每隔一秒轮询 - 压力大 - 复杂）

        CuratorFramework zkClient = CuratorFrameworkFactory.newClient(zkUrl, new RetryOneTime(1000));
        //启动和zookeeper的连接
        zkClient.start();

        try {
            //获取节点下的子节点/pay-server-config根目录，下面的每一个子节点都代表一项配置
            List<String> configNames = zkClient.getChildren().forPath("/" + nodename);

            for (String configName : configNames) {
                String value = new String(zkClient.getData().forPath("/" + nodename + "/" + configName));
                remoteProperties.put(configName, value);
            }

            //java代码用watch功能 -- 不同客户端不同写法，本质一样 ---NIO长连接底层网络编程技术
            TreeCache treeCache = new TreeCache(zkClient, "/" + nodename);
            treeCache.start();
            treeCache.getListenable().addListener(new TreeCacheListener() {
                @Override
                public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                    System.out.println("数据有变化，自动触发这段代码知晓！");
                    switch (event.getType()) {
                        case NODE_UPDATED:
                            System.out.println("数据发送变化！");
                            /**
                             * path : /pay-server-config/pay.alipay.url
                             * 这里包含具体哪一项配置发生变化
                             */
                            String configName = event.getData().getPath().replace("/" + nodename + "/", "");
                            String value = new String(event.getData().getData());
                            //更新本地配置项
                            remoteProperties.put(configName, value);
                            break;
                        default:
                            break;
                    }
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
